package io.itit.ecp.admin.provide.action.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.common.enums.IDeviceEnums;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.common.enums.ProductTypeActiveStatus;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.service.*;
import io.itit.grass.common.provide.action.resp.ResultResp;
import io.swagger.annotations.Api;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 运行优化
 */
@Api(tags = "运行优化")
@RestController
@RequestMapping("/ecp-admin/runtimeOptimizationReport/")
public class RuntimeOptimizationReportController {

    @Resource
    private IProductTypeService productTypeService;

    @Resource
    private IEnergyConsumptionTypeService energyConsumptionTypeService;

    @Resource
    private IMeterDeviceService meterDeviceService;

    @Resource
    private ISceneProjectService sceneProjectService;

    @Resource
    private ISceneEdificeService sceneEdificeService;

    @Resource
    private ISceneFloorService sceneFloorService;

    @Resource
    private ISceneRoomService sceneRoomService;

    @Resource
    private IPhysicalModelService physicalModelService;

    /**
     * 重点设备能耗说明- 分类统计能耗情况
     */
    @GetMapping("focus/energyConsumption")
    public ResultResp<Map<String, Object>> focusEnergyConsumption(String sceneProjectId,
                                                                  String sceneEdificeId,
                                                                  String sceneFloorId,
                                                                  String sceneRoomId,
                                                                  String startDate, String endDate) {
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        Set<String> sceneEdificeIds = StringUtils.isEmpty(sceneEdificeId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneEdificeId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        Set<String> sceneFloorIds = StringUtils.isEmpty(sceneFloorId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneFloorId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        Set<String> sceneRoomIds = StringUtils.isEmpty(sceneRoomId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneRoomId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add("ecp_tt_meter_device.product_type_id", "productTypeId", false)
                        .add("SUM(ecp_tt_energy_data.standard_coal)", "standardCoal", false))
                .innerJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .eq(MeterDeviceEntity::getIsFocus, "1")
                .isNotNull(MeterDeviceEntity::getProductTypeId)
                .groupBy(MeterDeviceEntity::getProductTypeId)
                .end()
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .in(CollectionUtils.isNotEmpty(sceneEdificeIds), EnergyDataEntity::getSceneEdificeId, sceneEdificeIds)
                .in(CollectionUtils.isNotEmpty(sceneFloorIds), EnergyDataEntity::getSceneFloorId, sceneFloorIds)
                .in(CollectionUtils.isNotEmpty(sceneRoomIds), EnergyDataEntity::getSceneRoomId, sceneRoomIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class);
        List<ProductTypeEntity> productTypeEntities = productTypeService.list(new LambdaQueryWrapper<ProductTypeEntity>()
                .eq(ProductTypeEntity::getActiveStatus, ProductTypeActiveStatus.ENABLED.getValue())
                .orderByAsc(ProductTypeEntity::getProductTypeCode));
        List<Map<String, Object>> dataList = new ArrayList<>();
        for (ProductTypeEntity productType : productTypeEntities) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", productType.getProductTypeName());
            map.put("value", energyDataEntities.stream().filter(item -> StringUtils.equals(productType.getId(), item.getProductTypeId()))
                    .findFirst().map(EnergyDataEntity::getStandardCoal).orElse(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP));
            dataList.add(map);
        }
        Map<String, Object> resultData = new HashMap<>(3);
        resultData.put("startTime", Objects.isNull(start) ? null : start.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        resultData.put("endTime", end.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        resultData.put("dataList", dataList);
        return ResultResp.success(resultData);
    }

    private LocalDateTime getStartDate(String startDate) {
        return StringUtils.isNotEmpty(startDate) ? LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
    }

    private LocalDateTime getEndDate(String endDate) {
        return StringUtils.isNotEmpty(endDate) ? LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
    }

    /**
     * 用电设备的能效情况分析- 分类统计能效情况
     */
    @GetMapping("electrical/energyConsumption")
    public ResultResp<Map<String, Object>> electricalEnergyConsumption(String sceneProjectId,
                                                                       String sceneEdificeId,
                                                                       String sceneFloorId,
                                                                       String sceneRoomId,
                                                                       String startDate, String endDate) {
        Set<String> sceneEdificeIds = StringUtils.isEmpty(sceneEdificeId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneEdificeId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        Set<String> sceneFloorIds = StringUtils.isEmpty(sceneFloorId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneFloorId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        Set<String> sceneRoomIds = StringUtils.isEmpty(sceneRoomId) ? Collections.emptySet() : Arrays.stream(StringUtils.split(sceneRoomId, ",")).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        List<Map<String, Object>> list = meterDeviceService.listMaps(new QueryWrapper<MeterDeviceEntity>()
                .select("energy_type_id", "COUNT(id) AS count_value")
                .eq(StringUtils.isNotEmpty(sceneProjectId), "scene_project_id", sceneProjectId)
                .in(CollectionUtils.isNotEmpty(sceneEdificeIds), "scene_edifice_id", sceneEdificeIds)
                .in(CollectionUtils.isNotEmpty(sceneFloorIds), "scene_floor_id", sceneFloorIds)
                .in(CollectionUtils.isNotEmpty(sceneRoomIds), "scene_room_id", sceneRoomIds)
                .eq("del_flag", IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .groupBy("energy_type_id")
        );
        String id = energyConsumptionTypeService.getElectricId();
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add("ecp_tt_meter_device.product_type_id", "productTypeId", false)
                        .add("SUM(ecp_tt_energy_data.meter_value)", "meterValue", false))
                .innerJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .eq(MeterDeviceEntity::getIsFocus, "1")
                .eq(MeterDeviceEntity::getEnergyTypeId, id)
                .isNotNull(MeterDeviceEntity::getProductTypeId)
                .groupBy(MeterDeviceEntity::getProductTypeId)
                .end()
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .in(CollectionUtils.isNotEmpty(sceneEdificeIds), EnergyDataEntity::getSceneEdificeId, sceneEdificeIds)
                .in(CollectionUtils.isNotEmpty(sceneFloorIds), EnergyDataEntity::getSceneFloorId, sceneFloorIds)
                .in(CollectionUtils.isNotEmpty(sceneRoomIds), EnergyDataEntity::getSceneRoomId, sceneRoomIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class);
        List<ProductTypeEntity> productTypeEntities = productTypeService.list(new LambdaQueryWrapper<ProductTypeEntity>()
                .eq(ProductTypeEntity::getActiveStatus, ProductTypeActiveStatus.ENABLED.getValue())
                .orderByAsc(ProductTypeEntity::getProductTypeCode));
        List<Map<String, Object>> dataList = new ArrayList<>();
        for (ProductTypeEntity productType : productTypeEntities) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", productType.getProductTypeName());
            BigDecimal totalMeterValue = energyDataEntities.stream().filter(item -> StringUtils.equals(productType.getId(), item.getProductTypeId()))
                    .findFirst().map(EnergyDataEntity::getMeterValue).orElse(BigDecimal.ZERO);
            int countValue = list.stream().filter(item -> StringUtils.equals((String) item.get("energy_type_id"), productType.getId()))
                    .findFirst().map(item -> item.containsKey("count_value") ? Integer.parseInt(item.get("count_value").toString()) : 0).orElse(0);
            BigDecimal value = countValue == 0 ? BigDecimal.ZERO : totalMeterValue.divide(new BigDecimal(String.valueOf(countValue)), 2, RoundingMode.HALF_DOWN);
            map.put("value", value);
            dataList.add(map);
        }
        Map<String, Object> resultData = new HashMap<>(3);
        resultData.put("startTime", Objects.isNull(start) ? null : start.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        resultData.put("endTime", end.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        resultData.put("dataList", dataList);
        return ResultResp.success(resultData);
    }

    /**
     * 查询电梯能耗情况
     */
    @GetMapping("elevator")
    public ResultResp<List<Map<String, Object>>> elevatorList(@RequestParam(required = false) String sceneProjectId,
                                                              @RequestParam(required = false) String sceneEdificeId,
                                                              @RequestParam(required = false) String sceneFloorId,
                                                              @RequestParam(required = false) String sceneRoomId,
                                                              @RequestParam(required = false) String startDate,
                                                              @RequestParam(required = false) String endDate) {
        List<ProductTypeEntity> productTypeEntities = productTypeService.getElevator();
        List<MeterDeviceEntity> meterDevices = meterDeviceService.lambdaQuery()
                .select(MeterDeviceEntity::getId, MeterDeviceEntity::getDeviceName, MeterDeviceEntity::getDeviceCode)
                .in(CollectionUtils.isNotEmpty(productTypeEntities),MeterDeviceEntity::getProductTypeId,
                        productTypeEntities.stream().map(ProductTypeEntity::getId).collect(Collectors.toSet()))
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDevices.stream().map(MeterDeviceEntity::getId).collect(Collectors.toSet());
        if (meterDeviceIds.isEmpty()) {
            return ResultResp.success(Collections.emptyList());
        }
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add(EnergyDataEntity::getMeterDeviceId)
                        .add(EnergyDataEntity::getSceneProjectId)
                        .add(EnergyDataEntity::getSceneEdificeId)
                        .add("SUM(ecp_tt_energy_data.meter_value)", "meterValue", false)
                )
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.isNotEmpty(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.isNotEmpty(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(StringUtils.isNotEmpty(sceneRoomId), EnergyDataEntity::getSceneRoomId, sceneRoomId)
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getMeterDeviceId, EnergyDataEntity::getSceneProjectId, EnergyDataEntity::getSceneEdificeId)
                .joinList(EnergyDataEntity.class);
        Set<String> projectIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneProjectId).collect(Collectors.toSet());
        Map<String, SceneProjectEntity> projectEntities = projectIds.isEmpty() ? Collections.emptyMap() : sceneProjectService.listByIds(projectIds).stream()
                .collect(Collectors.toMap(SceneProjectEntity::getId, Function.identity()));

        Set<String> sceneEdificeIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneEdificeId).collect(Collectors.toSet());
        Map<String, SceneEdificeEntity> edificeEntities = sceneEdificeIds.isEmpty() ? Collections.emptyMap() : sceneEdificeService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneEdificeEntity::getId, Function.identity()));

        Set<String> floorIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneFloorId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneFloorEntity> floorEntities = floorIds.isEmpty() ? Collections.emptyMap() : sceneFloorService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneFloorEntity::getId, Function.identity()));

        Set<String> roomIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneRoomId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneRoomEntity> roomEntities = roomIds.isEmpty() ? Collections.emptyMap() : sceneRoomService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneRoomEntity::getId, Function.identity()));
        List<Map<String, Object>> result = new ArrayList<>();
        for (EnergyDataEntity item : energyDataEntities) {
            Map<String, Object> map = new HashMap<>();
            String sceneEdificeName = edificeEntities.containsKey(item.getSceneEdificeId()) ? edificeEntities.get(item.getSceneEdificeId()).getEdificeName() : null;
            map.put("sceneProjectId", item.getSceneProjectId());
            map.put("sceneProjectName", projectEntities.containsKey(item.getSceneProjectId()) ? projectEntities.get(item.getSceneProjectId()).getProjectName() : null);
            map.put("sceneEdificeId", item.getSceneEdificeId());
            map.put("sceneEdificeName", sceneEdificeName);
            map.put("meterDeviceId", item.getMeterDeviceId());
            List<String> sceneInfos = new ArrayList<>();
            if (StringUtils.isNotEmpty(sceneEdificeName)) {
                sceneInfos.add(sceneEdificeName);
            }
            String sceneFloorName = floorEntities.containsKey(item.getSceneFloorId()) ? floorEntities.get(item.getSceneFloorId()).getFloorName() : null;
            if (StringUtils.isNotEmpty(sceneFloorName)) {
                sceneInfos.add(sceneFloorName);
            }
            String sceneRoomName = roomEntities.containsKey(item.getSceneRoomId()) ? roomEntities.get(item.getSceneRoomId()).getRoomName() : null;
            if (StringUtils.isNotEmpty(sceneRoomName)) {
                sceneInfos.add(sceneRoomName);
            }
            map.put("sceneInfo", String.join("/", sceneInfos));
            map.put("meterDeviceName", meterDevices.stream().filter(meterDevice -> StringUtils.equals(meterDevice.getId(), item.getMeterDeviceId()))
                    .findFirst().map(MeterDeviceEntity::getDeviceName).orElse(null));
            map.put("meterValue", item.getMeterValue().setScale(2, RoundingMode.HALF_UP));
            result.add(map);
        }
        return ResultResp.success(result);
    }


    /**
     * 查询充电桩能耗情况
     */
    @GetMapping("chargingStation")
    public ResultResp<List<Map<String, Object>>> chargingStationList(@RequestParam(required = false) String sceneProjectId,
                                                                     @RequestParam(required = false) String sceneEdificeId,
                                                                     @RequestParam(required = false) String sceneFloorId,
                                                                     @RequestParam(required = false) String sceneRoomId,
                                                                     @RequestParam(required = false) String startDate,
                                                                     @RequestParam(required = false) String endDate) {
        List<ProductTypeEntity> productTypeEntities = productTypeService.getChargingStation();
        List<MeterDeviceEntity> meterDevices = meterDeviceService.lambdaQuery()
                .select(MeterDeviceEntity::getId, MeterDeviceEntity::getDeviceName, MeterDeviceEntity::getDeviceCode)
                .in(CollectionUtils.isNotEmpty(productTypeEntities),MeterDeviceEntity::getProductTypeId, productTypeEntities.stream().map(ProductTypeEntity::getId).collect(Collectors.toSet()))
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDevices.stream().map(MeterDeviceEntity::getId).collect(Collectors.toSet());
        if (meterDeviceIds.isEmpty()) {
            return ResultResp.success(Collections.emptyList());
        }
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add(EnergyDataEntity::getMeterDeviceId)
                        .add(EnergyDataEntity::getSceneProjectId)
                        .add(EnergyDataEntity::getSceneEdificeId)
                        .add("SUM(ecp_tt_energy_data.meter_value)", "meterValue", false)
                )
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.isNotEmpty(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.isNotEmpty(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(StringUtils.isNotEmpty(sceneRoomId), EnergyDataEntity::getSceneRoomId, sceneRoomId)
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getMeterDeviceId, EnergyDataEntity::getSceneProjectId, EnergyDataEntity::getSceneEdificeId)
                .joinList(EnergyDataEntity.class);
        Set<String> projectIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneProjectId).collect(Collectors.toSet());
        Map<String, SceneProjectEntity> projectEntities = projectIds.isEmpty() ? Collections.emptyMap() : sceneProjectService.listByIds(projectIds).stream()
                .collect(Collectors.toMap(SceneProjectEntity::getId, Function.identity()));

        Set<String> sceneEdificeIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneEdificeId).collect(Collectors.toSet());
        Map<String, SceneEdificeEntity> edificeEntities = sceneEdificeIds.isEmpty() ? Collections.emptyMap() : sceneEdificeService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneEdificeEntity::getId, Function.identity()));

        Set<String> floorIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneFloorId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneFloorEntity> floorEntities = floorIds.isEmpty() ? Collections.emptyMap() : sceneFloorService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneFloorEntity::getId, Function.identity()));

        Set<String> roomIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneRoomId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneRoomEntity> roomEntities = roomIds.isEmpty() ? Collections.emptyMap() : sceneRoomService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneRoomEntity::getId, Function.identity()));
        List<Map<String, Object>> result = new ArrayList<>();
        for (EnergyDataEntity item : energyDataEntities) {
            Map<String, Object> map = new HashMap<>();
            String sceneEdificeName = edificeEntities.containsKey(item.getSceneEdificeId()) ? edificeEntities.get(item.getSceneEdificeId()).getEdificeName() : null;
            map.put("sceneProjectId", item.getSceneProjectId());
            map.put("sceneProjectName", projectEntities.containsKey(item.getSceneProjectId()) ? projectEntities.get(item.getSceneProjectId()).getProjectName() : null);
            map.put("sceneEdificeId", item.getSceneEdificeId());
            map.put("sceneEdificeName", sceneEdificeName);
            map.put("meterDeviceId", item.getMeterDeviceId());
            List<String> sceneInfos = new ArrayList<>();
            if (StringUtils.isNotEmpty(sceneEdificeName)) {
                sceneInfos.add(sceneEdificeName);
            }
            String sceneFloorName = floorEntities.containsKey(item.getSceneFloorId()) ? floorEntities.get(item.getSceneFloorId()).getFloorName() : null;
            if (StringUtils.isNotEmpty(sceneFloorName)) {
                sceneInfos.add(sceneFloorName);
            }
            String sceneRoomName = roomEntities.containsKey(item.getSceneRoomId()) ? roomEntities.get(item.getSceneRoomId()).getRoomName() : null;
            if (StringUtils.isNotEmpty(sceneRoomName)) {
                sceneInfos.add(sceneRoomName);
            }
            map.put("sceneInfo", String.join("/", sceneInfos));
            map.put("meterDeviceName", meterDevices.stream().filter(meterDevice -> StringUtils.equals(meterDevice.getId(), item.getMeterDeviceId()))
                    .findFirst().map(MeterDeviceEntity::getDeviceName).orElse(null));
            map.put("meterValue", item.getMeterValue().setScale(2, RoundingMode.HALF_UP)); //用电量
            result.add(map);
        }
        return ResultResp.success(result);
    }


    /**
     * 查询电梯能效情况
     */
    @GetMapping("elevator/efficiency")
    public ResultResp<List<Map<String, Object>>> elevatorEfficiencyList(@RequestParam(required = false) String sceneProjectId,
                                                                        @RequestParam(required = false) String sceneEdificeId,
                                                                        @RequestParam(required = false) String sceneFloorId,
                                                                        @RequestParam(required = false) String sceneRoomId,
                                                                        @RequestParam(required = false) String startDate,
                                                                        @RequestParam(required = false) String endDate) {
        List<ProductTypeEntity> productTypeEntities = productTypeService.getElevator();
        List<MeterDeviceEntity> meterDevices = meterDeviceService.lambdaQuery()
                .select(MeterDeviceEntity::getId, MeterDeviceEntity::getDeviceName, MeterDeviceEntity::getDeviceCode)
                .in(CollectionUtils.isNotEmpty(productTypeEntities),MeterDeviceEntity::getProductTypeId, productTypeEntities.stream().map(ProductTypeEntity::getId).collect(Collectors.toSet()))
                .eq(MeterDeviceEntity::getIsFocus, IDeviceEnums.IsFocus.isFocus1.isFocus)
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDevices.stream().map(MeterDeviceEntity::getId).collect(Collectors.toSet());
        if (meterDeviceIds.isEmpty()) {
            return ResultResp.success(Collections.emptyList());
        }
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add(EnergyDataEntity::getMeterDeviceId)
                        .add(EnergyDataEntity::getSceneProjectId)
                        .add(EnergyDataEntity::getSceneEdificeId)
                        .add("SUM(ecp_tt_energy_data.meter_value)", "meterValue", false)
                )
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.isNotEmpty(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.isNotEmpty(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(StringUtils.isNotEmpty(sceneRoomId), EnergyDataEntity::getSceneRoomId, sceneRoomId)
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getMeterDeviceId, EnergyDataEntity::getSceneProjectId, EnergyDataEntity::getSceneEdificeId)
                .joinList(EnergyDataEntity.class);
        Set<String> projectIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneProjectId).collect(Collectors.toSet());
        Map<String, SceneProjectEntity> projectEntities = projectIds.isEmpty() ? Collections.emptyMap() : sceneProjectService.listByIds(projectIds).stream()
                .collect(Collectors.toMap(SceneProjectEntity::getId, Function.identity()));

        Set<String> sceneEdificeIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneEdificeId).collect(Collectors.toSet());
        Map<String, SceneEdificeEntity> edificeEntities = sceneEdificeIds.isEmpty() ? Collections.emptyMap() : sceneEdificeService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneEdificeEntity::getId, Function.identity()));

        Set<String> floorIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneFloorId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneFloorEntity> floorEntities = floorIds.isEmpty() ? Collections.emptyMap() : sceneFloorService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneFloorEntity::getId, Function.identity()));

        Set<String> roomIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneRoomId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneRoomEntity> roomEntities = roomIds.isEmpty() ? Collections.emptyMap() : sceneRoomService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneRoomEntity::getId, Function.identity()));
        List<Map<String, Object>> result = new ArrayList<>();
        for (EnergyDataEntity item : energyDataEntities) {
            Map<String, Object> map = new HashMap<>();
            String sceneEdificeName = edificeEntities.containsKey(item.getSceneEdificeId()) ? edificeEntities.get(item.getSceneEdificeId()).getEdificeName() : null;
            map.put("sceneProjectId", item.getSceneProjectId());
            map.put("sceneProjectName", projectEntities.containsKey(item.getSceneProjectId()) ? projectEntities.get(item.getSceneProjectId()).getProjectName() : null);
            map.put("sceneEdificeId", item.getSceneEdificeId());
            map.put("sceneEdificeName", sceneEdificeName);
            map.put("meterDeviceId", item.getMeterDeviceId());
            List<String> sceneInfos = new ArrayList<>();
            if (StringUtils.isNotEmpty(sceneEdificeName)) {
                sceneInfos.add(sceneEdificeName);
            }
            String sceneFloorName = floorEntities.containsKey(item.getSceneFloorId()) ? floorEntities.get(item.getSceneFloorId()).getFloorName() : null;
            if (StringUtils.isNotEmpty(sceneFloorName)) {
                sceneInfos.add(sceneFloorName);
            }
            String sceneRoomName = roomEntities.containsKey(item.getSceneRoomId()) ? roomEntities.get(item.getSceneRoomId()).getRoomName() : null;
            if (StringUtils.isNotEmpty(sceneRoomName)) {
                sceneInfos.add(sceneRoomName);
            }
            map.put("sceneInfo", String.join("/", sceneInfos));
            map.put("meterDeviceName", meterDevices.stream().filter(meterDevice -> StringUtils.equals(meterDevice.getId(), item.getMeterDeviceId()))
                    .findFirst().map(MeterDeviceEntity::getDeviceName).orElse(null));
            BigDecimal meterValue = item.getMeterValue().setScale(2, RoundingMode.HALF_UP);
            map.put("meterValue", meterValue);
            BigDecimal power = physicalModelService.queryRunningDataValue(item.getMeterDeviceId(), "功率", start, end);
            BigDecimal runningTime = physicalModelService.queryRunningDataValue(item.getMeterDeviceId(), "运行时间", start, end);
            map.put("power", power); //设备功率
            map.put("runningTime", runningTime); //运行时间
            // 能效=(功率x开机时间）/用电量*100%（只保留两位数，小数四舍五入）
            map.put("efficiency", power.multiply(runningTime)
                    .divide(meterValue, 2, RoundingMode.HALF_DOWN)
                    .divide(new BigDecimal("100"),
                            2, RoundingMode.HALF_DOWN));
            result.add(map);
        }
        return ResultResp.success(result);
    }


    /**
     * 查询空调能效情况
     */
    @GetMapping("airConditioning/efficiency")
    public ResultResp<List<Map<String, Object>>> chargingStationEfficiencyList(@RequestParam(required = false) String sceneProjectId,
                                                                               @RequestParam(required = false) String sceneEdificeId,
                                                                               @RequestParam(required = false) String sceneFloorId,
                                                                               @RequestParam(required = false) String sceneRoomId,
                                                                               @RequestParam(required = false) String startDate,
                                                                               @RequestParam(required = false) String endDate) {
        List<ProductTypeEntity> productTypeEntities = productTypeService.getAirConditioning();
        List<MeterDeviceEntity> meterDevices = meterDeviceService.lambdaQuery()
                .select(MeterDeviceEntity::getId, MeterDeviceEntity::getDeviceName, MeterDeviceEntity::getDeviceCode)
                .in(CollectionUtils.isNotEmpty(productTypeEntities),MeterDeviceEntity::getProductTypeId, productTypeEntities.stream().map(ProductTypeEntity::getId).collect(Collectors.toSet()))
                .eq(MeterDeviceEntity::getIsFocus, IDeviceEnums.IsFocus.isFocus1.isFocus)
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDevices.stream().map(MeterDeviceEntity::getId).collect(Collectors.toSet());
        if (meterDeviceIds.isEmpty()) {
            return ResultResp.success(Collections.emptyList());
        }
        LocalDateTime start = getStartDate(startDate);
        LocalDateTime end = getEndDate(endDate);
        List<EnergyDataEntity> energyDataEntities = Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add(EnergyDataEntity::getMeterDeviceId)
                        .add(EnergyDataEntity::getSceneProjectId)
                        .add(EnergyDataEntity::getSceneEdificeId)
                        .add("SUM(ecp_tt_energy_data.meter_value)", "meterValue", false)
                )
                .eq(StringUtils.isNotEmpty(sceneProjectId), EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .eq(StringUtils.isNotEmpty(sceneEdificeId), EnergyDataEntity::getSceneEdificeId, sceneEdificeId)
                .eq(StringUtils.isNotEmpty(sceneFloorId), EnergyDataEntity::getSceneFloorId, sceneFloorId)
                .eq(StringUtils.isNotEmpty(sceneRoomId), EnergyDataEntity::getSceneRoomId, sceneRoomId)
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyDataEntity::getSolidifyDate, end)
                .groupBy(EnergyDataEntity::getMeterDeviceId, EnergyDataEntity::getSceneProjectId, EnergyDataEntity::getSceneEdificeId)
                .joinList(EnergyDataEntity.class);
        Set<String> projectIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneProjectId).collect(Collectors.toSet());
        Map<String, SceneProjectEntity> projectEntities = projectIds.isEmpty() ? Collections.emptyMap() : sceneProjectService.listByIds(projectIds).stream()
                .collect(Collectors.toMap(SceneProjectEntity::getId, Function.identity()));

        Set<String> sceneEdificeIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneEdificeId).collect(Collectors.toSet());
        Map<String, SceneEdificeEntity> edificeEntities = sceneEdificeIds.isEmpty() ? Collections.emptyMap() : sceneEdificeService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneEdificeEntity::getId, Function.identity()));

        Set<String> floorIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneFloorId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneFloorEntity> floorEntities = floorIds.isEmpty() ? Collections.emptyMap() : sceneFloorService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneFloorEntity::getId, Function.identity()));

        Set<String> roomIds = energyDataEntities.stream().map(EnergyDataEntity::getSceneRoomId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<String, SceneRoomEntity> roomEntities = roomIds.isEmpty() ? Collections.emptyMap() : sceneRoomService.listByIds(sceneEdificeIds).stream()
                .collect(Collectors.toMap(SceneRoomEntity::getId, Function.identity()));
        List<Map<String, Object>> result = new ArrayList<>();
        for (EnergyDataEntity item : energyDataEntities) {
            Map<String, Object> map = new HashMap<>();
            String sceneEdificeName = edificeEntities.containsKey(item.getSceneEdificeId()) ? edificeEntities.get(item.getSceneEdificeId()).getEdificeName() : null;
            map.put("sceneProjectId", item.getSceneProjectId());
            map.put("sceneProjectName", projectEntities.containsKey(item.getSceneProjectId()) ? projectEntities.get(item.getSceneProjectId()).getProjectName() : null);
            map.put("sceneEdificeId", item.getSceneEdificeId());
            map.put("sceneEdificeName", sceneEdificeName);
            map.put("meterDeviceId", item.getMeterDeviceId());
            List<String> sceneInfos = new ArrayList<>();
            if (StringUtils.isNotEmpty(sceneEdificeName)) {
                sceneInfos.add(sceneEdificeName);
            }
            String sceneFloorName = floorEntities.containsKey(item.getSceneFloorId()) ? floorEntities.get(item.getSceneFloorId()).getFloorName() : null;
            if (StringUtils.isNotEmpty(sceneFloorName)) {
                sceneInfos.add(sceneFloorName);
            }
            String sceneRoomName = roomEntities.containsKey(item.getSceneRoomId()) ? roomEntities.get(item.getSceneRoomId()).getRoomName() : null;
            if (StringUtils.isNotEmpty(sceneRoomName)) {
                sceneInfos.add(sceneRoomName);
            }
            map.put("sceneInfo", String.join("/", sceneInfos));
            map.put("meterDeviceName", meterDevices.stream().filter(meterDevice -> StringUtils.equals(meterDevice.getId(), item.getMeterDeviceId()))
                    .findFirst().map(MeterDeviceEntity::getDeviceName).orElse(null));

            BigDecimal meterValue = item.getMeterValue().setScale(2, RoundingMode.HALF_UP);
            map.put("meterValue", meterValue);
            BigDecimal power = physicalModelService.queryRunningDataValue(item.getMeterDeviceId(), "功率", start, end);
            BigDecimal runningTime = physicalModelService.queryRunningDataValue(item.getMeterDeviceId(), "运行时间", start, end);
            map.put("power", power); //设备功率
            map.put("runningTime", runningTime); //运行时间
            // 能效=(功率x开机时间）/用电量*100%（只保留两位数，小数四舍五入）
            map.put("efficiency", power.multiply(runningTime)
                    .divide(meterValue, 2, RoundingMode.HALF_DOWN)
                    .divide(new BigDecimal("100"),
                            2, RoundingMode.HALF_DOWN));
            result.add(map);
        }
        return ResultResp.success(result);
    }

}
